import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class AllCreatures implements Iterable<Fish> {
    private List<Fish> allAnimals;
    private List<Obstacle> allObstacles;
    private int MAX_X;
    private int MAX_Y;

    public AllCreatures(int victims, int predators, int obstacles, int maxX, int maxY) {
        allAnimals = new ArrayList<Fish>();
        allObstacles = new ArrayList<Obstacle>();
        MAX_X = maxX;
        MAX_Y = maxY;

        create(victims, CreaturesType.Victim);
        create(predators, CreaturesType.Predator);
        create(obstacles, CreaturesType.Obstacle);
    }


    public boolean add(Fish fish) {
        if (fish != null && !isObstacleOnPosition(fish.getPosition())) {
            allAnimals.add(fish);
            return true;
        }
        return false;
    }

    public void add(Obstacle obstacle) {
        if (obstacle != null && !isObstacleOnPosition(obstacle.getPosition())) {
            allObstacles.add(obstacle);
        }
    }

    public void remove(Fish fish) {
        allAnimals.remove(fish);
    }

    public void remove(Obstacle obstacle) {
        allObstacles.remove(obstacle);
    }

    public void create(int quantity, CreaturesType type) {
        if (quantity > 0) {
            switch (type) {
                case Victim:
                    for (int i = 0; i < quantity; i++) {
                        Position position = new Position(MAX_X, MAX_Y);
                        while (!allAnimals.add(new Victim(position))) {
                            position = new Position(MAX_X, MAX_Y);
                            System.out.println(position);
                        }
                    }
                    break;
                case Predator:
                    for (int i = 0; i < quantity; i++) {
                        Position position = new Position(MAX_X, MAX_Y);
                        while (isObstacleOnPosition(position)) {
                            position = new Position(MAX_X, MAX_Y);
                        }
                        allAnimals.add(new Predator(position));
                    }
                    break;
                case Obstacle:
                    for (int i = 0; i < quantity; i++) {
                        Position position = new Position(MAX_X, MAX_Y);
                        while (isObstacleOnPosition(position)) {
                            position = new Position(MAX_X, MAX_Y);
                        }
                        allObstacles.add(new Obstacle(position));
                    }
                    break;
                default:
                    break;
            }
        }
    }

    public boolean isVictimOnPosition(Position position) {
        boolean result = false;
        for (Fish fish : allAnimals) {
            if (fish.getPosition().equals(position) && fish.getType() == CreaturesType.Victim) {
                result = true;
                break;
            }
        }
        return result;
    }

    public Victim firstVictimOnPosition(Position position) {
        for (Fish fish : allAnimals) {
            if (fish.getPosition().equals(position)&&fish.getType()==CreaturesType.Victim) {
                return (Victim) fish;
            }
        }
        return null;
    }

    public boolean isObstacleOnPosition(Position position) {
        boolean result = false;
        for (Obstacle obstacle : allObstacles) {
            if (obstacle.getPosition().equals(position)) {
                result = true;
                break;
            }
        }
        return result;
    }

    private Iterable<Victim> returnAllVictims() {
        List<Victim> victimsList = new ArrayList<Victim>();
        for (Fish fish : allAnimals) {
            if (fish.getType() == CreaturesType.Victim) {
                victimsList.add((Victim) fish);
            }
        }
        return victimsList;
    }

    public MotionInformation findNearestVictim(Position predatorPosition, int maxStep) {
        int step = 1;
        Direction resultDirection = Direction.FAKE;
        Iterable<Victim> victims = returnAllVictims();

        while (step <= maxStep) {
            for (int direction = 0; direction < Direction.values().length; direction++) {
                for (Victim victim : victims) {
                    resultDirection=Direction.values()[direction];
                    Position newPosition = Position.getNewPosition(predatorPosition, new MotionInformation(resultDirection, step));
                    if (victim.getPosition().equals(newPosition)) {
                        return new MotionInformation(resultDirection,step);
                    }
                }
            }
            step++;
        }
        return new MotionInformation(resultDirection,step);
    }

    public void clear() {
       Fish fish = null;
       for (int i = 0; i < allAnimals.size(); i++) {
            fish = allAnimals.get(i);
            if (fish.isDead()) {
                remove(fish);
           }
       }
    }

    @Override
    public String toString() {
        StringBuffer creaturesString = new StringBuffer();
        for (Fish fish : allAnimals) {
            creaturesString.append(fish);
            creaturesString.append("\n");
        }
        for (Obstacle obstacle : allObstacles) {
            creaturesString.append(obstacle);
            creaturesString.append("\n");
        }
        return creaturesString.toString();
    }

    @Override
    public Iterator<Fish> iterator() {
        return allAnimals.iterator();
    }


}
